import Foundation

// WebSocket状态枚举
enum WebSocketState {
    case disconnected
    case connecting
    case connected
    case disconnecting
    case reconnecting
}

// WebSocket错误类型
enum WebSocketError: Error {
    case notConnected
    case connectionTimeout
    case sendFailed
    case receiveFailed
    case invalidURL
}

// WebSocket管理器
class WebSocketManager: NSObject {
    // MARK: - 配置参数
    private let url: URL
    private let headers: [String: String]?
    private let timeout: TimeInterval
    private let heartbeatInterval: TimeInterval
    private let maxReconnectAttempts: Int
    private let initialReconnectDelay: TimeInterval
    private let maxReconnectDelay: TimeInterval
    private let backoffFactor: Double
    
    // MARK: - 连接相关
    private var webSocketTask: URLSessionWebSocketTask?
    private var urlSession: URLSession?
    
    // MARK: - 状态管理
    private(set) var currentState: WebSocketState = .disconnected {
        didSet {
            print("WebSocket 状态变更: \(oldValue) → \(currentState)")
            NotificationCenter.default.post(
                name: .webSocketStateChanged,
                object: self,
                userInfo: ["state": currentState]
            )
        }
    }
    
    // MARK: - 重连相关
    private var reconnectTimer: Timer?
    private var currentReconnectAttempt = 0
    private var isReconnecting = false
    
    // MARK: - 心跳相关
    private var heartbeatTimer: Timer?
    
    // MARK: - 回调
    var onConnected: (() -> Void)?
    var onDisconnected: ((Error?) -> Void)?
    var onMessageReceived: ((String) -> Void)?
    var onDataReceived: ((Data) -> Void)?
    
    // MARK: - 初始化
    init(
        url: URL = URL(string: "wss://www.zhuiso.cn/wss/jcy/websocket/chat")!,
        headers: [String: String]? = nil,
        timeout: TimeInterval = 10.0,
        heartbeatInterval: TimeInterval = 30.0,
        maxReconnectAttempts: Int = 10,
        initialReconnectDelay: TimeInterval = 1.0,
        maxReconnectDelay: TimeInterval = 30.0,
        backoffFactor: Double = 2.0
    ) {
        self.url = url
        self.headers = headers
        self.timeout = timeout
        self.heartbeatInterval = heartbeatInterval
        self.maxReconnectAttempts = maxReconnectAttempts
        self.initialReconnectDelay = initialReconnectDelay
        self.maxReconnectDelay = maxReconnectDelay
        self.backoffFactor = backoffFactor
    }
    
    deinit {
        disconnect()
    }
    
    // MARK: - 公共方法
    func connect() {
        // 如果已经连接或正在连接，直接返回
        if currentState == .connected || currentState == .connecting {
            return
        }
        
        // 重置重连状态
        resetReconnectState()
        
        // 创建URLSession配置
        let config = URLSessionConfiguration.default
        headers?.forEach { key, value in
            config.httpAdditionalHeaders?[key] = value
        }
        
        // 创建URLSession
        urlSession = URLSession(
            configuration: config,
            delegate: self,
            delegateQueue: OperationQueue.main
        )
        
        // 创建WebSocket任务
        webSocketTask = urlSession?.webSocketTask(with: url)
        
        // 设置连接超时计时器
        let timeoutTimer = Timer.scheduledTimer(withTimeInterval: timeout, repeats: false) { [weak self] _ in
            guard let self = self else { return }
            
            if self.currentState == .connecting {
                print("❌ WebSocket连接超时")
                self.webSocketTask?.cancel(with: .abnormalClosure, reason: nil)
                self.currentState = .disconnected
                self.onDisconnected?(WebSocketError.connectionTimeout)
                self.startReconnect()
            }
        }
        
        // 更新状态并开始连接
        currentState = .connecting
        webSocketTask?.resume()
        print("🌐 正在连接到WebSocket: \(url.absoluteString)")
    }
    
    func disconnect(reason: String? = nil) {
        // 如果已经断开或正在断开，直接返回
        if currentState == .disconnected || currentState == .disconnecting {
            return
        }
        
        // 标记为主动断开，不触发重连
        isReconnecting = false
        currentState = .disconnecting
        
        // 停止心跳
        stopHeartbeat()
        
        // 优雅地关闭WebSocket连接
        webSocketTask?.cancel(
            with: .normalClosure,
            reason: reason?.data(using: .utf8)
        )
        
        // 清理资源
        webSocketTask = nil
        urlSession = nil
        reconnectTimer?.invalidate()
        reconnectTimer = nil
        
        // 更新状态
        currentState = .disconnected
        print("🔌 WebSocket已断开连接" + (reason != nil ? ": \(reason!)" : ""))
        onDisconnected?(nil)
    }
    
    func sendMessage(_ message: String, completion: ((Error?) -> Void)? = nil) {
        guard currentState == .connected else {
            print("❌ 无法发送消息：WebSocket未连接（状态: \(currentState)）")
            
            if currentState != .connecting && currentState != .reconnecting {
                startReconnect()
            }
            
            completion?(WebSocketError.notConnected)
            return
        }
        
        // 发送消息
        let message = URLSessionWebSocketTask.Message.string(message)
        webSocketTask?.send(message) { [weak self] error in
            if let error = error {
                print("❌ 消息发送失败: \(error.localizedDescription)")
                self?.startReconnect()
                completion?(WebSocketError.sendFailed)
            } else {
                print("📤 消息发送成功")
                completion?(nil)
            }
        }
    }
    
    // MARK: - 重连逻辑
    private func startReconnect() {
        // 如果已经在重连或者达到最大尝试次数，直接返回
        if isReconnecting || currentReconnectAttempt >= maxReconnectAttempts {
            return
        }
        
        isReconnecting = true
        currentState = .reconnecting
        currentReconnectAttempt += 1
        
        // 计算退避延迟
        let delay = min(
            initialReconnectDelay * pow(backoffFactor, Double(currentReconnectAttempt - 1)),
            maxReconnectDelay
        )
        
        print("🔄 计划在 \(delay) 秒后尝试重连 (第\(currentReconnectAttempt)/\(maxReconnectAttempts)次尝试)")
        
        reconnectTimer = Timer.scheduledTimer(withTimeInterval: delay, repeats: false) { [weak self] _ in
            guard let self = self else { return }
            
            print("🔄 尝试重连WebSocket...")
            self.connect()
        }
    }
    
    private func resetReconnectState() {
        isReconnecting = false
        currentReconnectAttempt = 0
        reconnectTimer?.invalidate()
        reconnectTimer = nil
    }
    
    // MARK: - 心跳机制
    private func startHeartbeat() {
        stopHeartbeat()
        
        heartbeatTimer = Timer.scheduledTimer(
            timeInterval: heartbeatInterval,
            target: self,
            selector: #selector(sendHeartbeat),
            userInfo: nil,
            repeats: true
        )
        
        // 立即发送一次心跳
        sendHeartbeat()
    }
    
    private func stopHeartbeat() {
        heartbeatTimer?.invalidate()
        heartbeatTimer = nil
    }
    
    @objc private func sendHeartbeat() {
        guard currentState == .connected else {
            print("💔 心跳发送失败：WebSocket未连接")
            return
        }
        
        // 发送心跳消息
        if (ViewModel.shared.passenger.openId.isEmpty){
            print("💔 心跳发送失败：无法获取openId")
            return
        }
        let sendData = """
         {
           "cmd":"ONHEART",
           "peopleId":"\(ViewModel.shared.passenger.openId)"
         }
      """
        sendMessage(sendData) { [weak self] error in
            if let error = error {
                print("💔 心跳发送失败: \(error.localizedDescription)")
                self?.startReconnect()
            } else {
                print("💓 心跳发送成功")
            }
        }
    }
    
    // MARK: - 消息接收
    private func startReceivingMessages() {
        guard currentState == .connected, let task = webSocketTask else {
            print("❌ 无法接收消息：WebSocket未连接")
            return
        }
        
        // 捕获强引用以确保任务执行期间对象不被释放
        task.receive { [weak self, strongTask = task] result in
            guard let self = self else { return }
            
            switch result {
            case .success(let message):
                switch message {
                case .string(let text):
                    print("📥 收到文本消息: \(text)")
                    self.onMessageReceived?(text)
                    
                case .data(let data):
                    print("📥 收到二进制数据: \(data.count) bytes")
                    self.onDataReceived?(data)
                    
                @unknown default:
                    print("❓ 收到未知类型的消息")
                }
                
                // 继续接收下一条消息
                self.continueReceivingMessages(with: strongTask)
                
            case .failure(let error):
                print("❌ 接收消息失败: \(error.localizedDescription)")
                
                // 如果连接已断开，尝试重连
                if self.webSocketTask?.state == .completed, self.currentState != .disconnected {
                    self.currentState = .disconnected
                    self.startReconnect()
                } else {
                    // 否则继续接收消息
                    self.continueReceivingMessages(with: strongTask)
                }
            }
        }
    }
    
    private func continueReceivingMessages(with task: URLSessionWebSocketTask) {
        guard currentState == .connected else {
            return
        }
        
        task.receive { [weak self, strongTask = task] result in
            guard let self = self else { return }
            
            switch result {
            case .success(let message):
                switch message {
                case .string(let text):
                    print("📥 收到文本消息: \(text)")
                    self.onMessageReceived?(text)
                    
                case .data(let data):
                    print("📥 收到二进制数据: \(data.count) bytes")
                    self.onDataReceived?(data)
                    
                @unknown default:
                    print("❓ 收到未知类型的消息")
                }
                
                // 继续接收下一条消息
                self.continueReceivingMessages(with: strongTask)
                
            case .failure(let error):
                print("❌ 接收消息失败: \(error.localizedDescription)")
                
                // 如果连接已断开，尝试重连
                if self.webSocketTask?.state == .completed, self.currentState != .disconnected {
                    self.currentState = .disconnected
                    self.startReconnect()
                } else {
                    // 否则继续接收消息
                    self.continueReceivingMessages(with: strongTask)
                }
            }
        }
    }
}

// MARK: - URLSessionWebSocketDelegate 实现
extension WebSocketManager: URLSessionWebSocketDelegate {
    func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) {
        print("✅ WebSocket连接成功")
        
        // 重置重连状态
        resetReconnectState()
        
        // 更新状态
        currentState = .connected
        
        // 启动心跳
        startHeartbeat()
        
        // 开始接收消息
        startReceivingMessages()
        
        // 触发连接成功回调
        onConnected?()
    }
    
    func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
        // 停止心跳
        stopHeartbeat()
        
        // 解析断开原因
        let reasonText = reason.flatMap { String(data: $0, encoding: .utf8) } ?? ""
        let closeCodeDescription = closeCode.description
        
        // 记录断开日志
        if currentState == .disconnecting {
            print("🔌 WebSocket正常断开: \(closeCodeDescription)")
        } else {
            print("❌ WebSocket意外断开: \(closeCodeDescription), 原因: \(reasonText)")
            
            // 如果需要重连
            if !isReconnecting {
                startReconnect()
            }
        }
        
        // 更新状态
        currentState = .disconnected
        
        // 触发断开回调
        if closeCode != .normalClosure {
            let error = NSError(
                domain: "WebSocketError",
                code: Int(closeCode.rawValue),
                userInfo: [NSLocalizedDescriptionKey: "WebSocket断开: \(closeCodeDescription)"]
            )
            onDisconnected?(error)
        } else {
            onDisconnected?(nil)
        }
    }
}

// MARK: - 通知扩展
extension Notification.Name {
    static let webSocketStateChanged = Notification.Name("WebSocketStateChanged")
}

extension URLSessionWebSocketTask.CloseCode {
    var description: String {
        switch self {
        case .normalClosure: return "正常关闭 (1000)"
        case .goingAway: return "端点离开 (1001)"
        case .protocolError: return "协议错误 (1002)"
        case .unsupportedData: return "不支持的数据类型 (1003)"
        case .noStatusReceived: return "没有状态码 (1005)"
        case .abnormalClosure: return "异常关闭 (1006)"
        case .invalidFramePayloadData: return "无效的帧负载数据 (1007)"
        case .policyViolation: return "策略冲突 (1008)"
        case .messageTooBig: return "消息太大 (1009)"
        case .internalServerError: return "服务器内部错误 (1011)"
        case .tlsHandshakeFailure: return "TLS握手失败 (1015)"
        default: return "未知关闭码 (\(rawValue))"
        }
    }
}
